<template>
    <div class="page_root" :key="queryUpdateFlag" data-page-name="定期定价优化" data-page-identification="u_sfffzudxlz">
      <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
        <!-- begin vid_xjg6gqqxpp 自定义模板_h1df8suis4 -->
        <div style="width:100%;height:100%;display: flex;flex-direction: column;position: relative">
          <div class="toolbar">
            <div class="toolbar-left">
              <div style="padding-right: 24px;">
                <div class="view-switcher">
                  <div class="view-switcher-item" :class="{active: viewType === 'marketArea'}" @click="changeViewType('marketArea')">销售区域视图</div>
                  <div class="view-switcher-item" :class="{active: viewType !== 'marketArea'}" @click="changeViewType('administrativeArea')">行政区域视图</div>
                </div>
              </div>
              <div>
                <a-select v-model:value="marketLayer" v-if="viewType === 'marketArea'" style="width:200px;">
                  <a-select-option value="marketCenter">营销中心维度</a-select-option>
                  <a-select-option value="marketDepartment">市场部维度</a-select-option>
                  <a-select-option value="marketArea">市场区域维度</a-select-option>
                </a-select>
                <a-select v-model:value="administrativeLayer" v-else style="width:200px;">
                  <a-select-option value="province">省维度</a-select-option>
                  <a-select-option value="city">地级市维度</a-select-option>
                </a-select>
              </div>
              <div>
                <a-select
                  v-if="viewType === 'marketArea' && marketLayer === 'marketCenter'"
                  v-model:value="searchForm.marketCenterId"
                  :options="marketCenterSearchOptions"
                  show-search
                  style="width: 200px"
                  allow-clear
                  option-filter-prop="label"
                  placeholder="请选择营销中心维度定位"
                  @change="handleMarketCenterChange"
                ></a-select>
                <a-select
                  v-if="viewType === 'marketArea' && marketLayer === 'marketDepartment'"
                  v-model:value="searchForm.marketDepartmentId"
                  :options="marketDepartmentSearchOptions"
                  show-search
                  style="width: 200px"
                  allow-clear
                  option-filter-prop="label"
                  placeholder="请选择市场部维度定位"
                  @change="handleMarketDepartmentChange"
                ></a-select>
                <a-select
                  v-if="viewType === 'marketArea' && marketLayer === 'marketArea'"
                  v-model:value="searchForm.marketAreaId"
                  :options="marketAreaSearchOptions"
                  show-search
                  style="width: 200px"
                  allow-clear
                  option-filter-prop="label"
                  placeholder="请选择市场区域维度定位"
                  @change="handleMarketAreaChange"
                ></a-select>
  
                <a-select
                  v-if="viewType !== 'marketArea' && administrativeLayer === 'province'"
                  v-model:value="searchForm.provinceCode"
                  :options="provinceSearchOptions"
                  show-search
                  style="width: 200px"
                  allow-clear
                  option-filter-prop="label"
                  placeholder="请选择省维度定位"
                  @change="handleProvinceChange"
                ></a-select>
                <a-select
                  v-if="viewType !== 'marketArea' && administrativeLayer === 'city'"
                  v-model:value="searchForm.cityCode"
                  :options="citySearchOptions"
                  show-search
                  style="width: 200px"
                  allow-clear
                  option-filter-prop="label"
                  placeholder="请选择地级市维度定位"
                  @change="handleCityChange"
                ></a-select>
              </div>
              <div>
                <a-select
                  v-model:value="searchForm.enterpriseId"
                  allow-clear
                  style="width:200px;"
                  show-search
                  placeholder="请输入企业名称关键字查找"
                  option-filter-prop="label"
                  :options="enterpriseList"
                  @change="handleEnterpriseChange"
                ></a-select>
              </div>
            </div>
            <div class="toolbar-right">
              <div v-show="viewType === 'marketArea'" style="background:#F5F5F5;border-radius: 2px;display: flex;flex-direction: row;">
                <div
                  style="cursor: pointer; padding: 4px 16px;background-image: linear-gradient(180deg, #F97863 0%, #D50017 100%);box-shadow: 0 2px 2px 0 #DCDCDC, inset 0 3px 3px 0 rgba(255,255,255,0.43);border-radius: 8px;color:#FFF;"
                  @click="showSimulateModal"
                >
                  模拟优化
                </div>
                <a-popconfirm v-if="simulating" title="请确认是否清除模拟数据？" @confirm="handleCleanSimulate">
                  <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;padding: 8px 9px;cursor: pointer" title="清除模拟数据">
                    <svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
                      <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
                        <g transform="translate(-1578, -73)" fill="#D7000F" fill-rule="nonzero">
                          <g transform="translate(1464, 64)">
                            <g transform="translate(114, 9)">
                              <path
                                d="M11.375,2.625 L11.375,13.125 L2.625,13.125 L2.625,2.625 L11.375,2.625 M12.25,1.75 L1.75,1.75 L1.75,13.125 C1.75,13.6078125 2.1421875,14 2.625,14 L11.375,14 C11.8578125,14 12.25,13.6078125 12.25,13.125 L12.25,1.75 Z"
                              ></path>
                              <path
                                d="M13.5625,1.75 L0.4375,1.75 C0.1953125,1.75 0,1.9453125 0,2.1875 C0,2.4296875 0.1953125,2.625 0.4375,2.625 L13.5625,2.625 C13.8046875,2.625 14,2.4296875 14,2.1875 C14,1.9453125 13.8046875,1.75 13.5625,1.75 Z"
                              ></path>
                              <path
                                d="M9.625,0.875 L9.625,1.75 L4.4296875,1.75 L4.4296875,0.875 L9.625,0.875 M9.625,0 L4.4296875,0 C3.946875,0 3.5546875,0.3921875 3.5546875,0.875 L3.5546875,2.625 L10.5,2.625 L10.5,0.875 C10.5,0.3921875 10.1078125,0 9.625,0 Z M4.8125,4.375 C4.5703125,4.375 4.375,4.5703125 4.375,4.8125 L4.375,10.9375 C4.375,11.1796875 4.5703125,11.375 4.8125,11.375 C5.0546875,11.375 5.25,11.1796875 5.25,10.9375 L5.25,4.8125 C5.25,4.5703125 5.0546875,4.375 4.8125,4.375 Z M7,4.375 C6.7578125,4.375 6.5625,4.5703125 6.5625,4.8125 L6.5625,10.9375 C6.5625,11.1796875 6.7578125,11.375 7,11.375 C7.2421875,11.375 7.4375,11.1796875 7.4375,10.9375 L7.4375,4.8125 C7.4375,4.5703125 7.2421875,4.375 7,4.375 Z M9.1875,4.375 C8.9453125,4.375 8.75,4.5703125 8.75,4.8125 L8.75,10.9375 C8.75,11.1796875 8.9453125,11.375 9.1875,11.375 C9.4296875,11.375 9.625,11.1796875 9.625,10.9375 L9.625,4.8125 C9.625,4.5703125 9.4296875,4.375 9.1875,4.375 Z"
                              ></path>
                            </g>
                          </g>
                        </g>
                      </g>
                    </svg>
                  </div>
                </a-popconfirm>
              </div>
              <div v-show="viewType !== 'marketArea'" style="background:#F5F5F5;padding: 4px 16px;border-radius: 2px;">
                <a-checkbox v-model:checked="layerConfig.inventoryLayerShow">熟料库存&库容比</a-checkbox>
                <a-tooltip title="按省/地级市维度，统计当前最新状态的“熟料总库存(万吨)”及“熟料总库容比”。">
                  <question-circle-outlined style="color:#D7000F" />
                </a-tooltip>
              </div>
              <div v-show="viewType !== 'marketArea'" style="background:#F5F5F5;padding: 4px 16px;border-radius: 2px;">
                <a-checkbox v-model:checked="layerConfig.salesVolumeLayerShow">市场销量&北方市占率</a-checkbox>
                <a-tooltip title="按省/地级市维度，统计最新月份销量“市场总销量(万吨)”及“北方水泥市占率”。">
                  <question-circle-outlined style="color:#D7000F" />
                </a-tooltip>
              </div>
              <div v-show="viewType === 'marketArea'" style="background:#F5F5F5;padding: 4px 16px;border-radius: 2px;">
                <a-checkbox v-model:checked="layerConfig.priceSystemLayerShow">价格体系</a-checkbox>
                <setting-outlined style="color:#D7000F" @click="showPriceSystemConfigModal" />
              </div>
              <div style="background:#F5F5F5;padding: 4px 16px;border-radius: 2px;">
                <a-checkbox v-model:checked="layerConfig.enterpriseLayerShow">企业分布</a-checkbox>
                <setting-outlined style="color:#D7000F" @click="showEnterpriseLayerConfigModal" />
              </div>
            </div>
          </div>
          <div id="MapContainer" style="width:100%;height:100%;flex:1;"></div>
  
          <div v-show="viewType !== 'marketArea'" class="metric-box-wrapper">
            <div class="metric-box" v-if="!isNaN(parseFloat(administrativeAreaInfo.totalInventory))">
              <div class="metric-item-box">
                <div class="metric-name">熟料总库存</div>
                <div class="metric-value-row">
                  <div class="metric-value">{{ parseFloat(administrativeAreaInfo.totalInventory).toFixed(2) }}</div>
                  <div class="metric-unit">万吨</div>
                </div>
              </div>
              <div class="metric-image metric-image-1"></div>
            </div>
  
            <div class="metric-box metric-2" v-if="!isNaN(parseFloat(administrativeAreaInfo.totalStorageCapacityRatio))">
              <div class="metric-item-box">
                <div class="metric-name">熟料库容比</div>
                <div class="metric-value-row">
                  <div class="metric-value">{{ parseFloat(administrativeAreaInfo.totalStorageCapacityRatio).toFixed(2) }}</div>
                  <div class="metric-unit">%</div>
                </div>
              </div>
              <div class="metric-image metric-image-2"></div>
            </div>
          </div>
          <div v-show="legendShow" class="legend-box">
            <div
              v-for="item in ['北方水泥', 'markerPng', '亚泰水泥', '金隅冀东', '蒙西水泥', '山水水泥', '天瑞水泥', '大鹰水泥', '海螺水泥']"
              style="display: flex;flex-direction: row;align-items: center"
            >
              <div style="width:40px;display: flex;flex-direction: row;justify-content: center;align-content: center">
                <img :src="logoMap[item]" alt="" :style="logoSize[item]" />
              </div>
              <div style="flex:1;">{{ item === 'markerPng' ? '北方水泥-窑磨一体': item }}</div>
            </div>
            <div style="display: flex;flex-direction: row;">
              <div style="width:40px;display: flex;flex-direction: row;justify-content: center;align-content: center">
                <div style="width:10px;height:10px;border-radius: 50%;background:#262626"></div>
              </div>
              <div style="flex:1;">其它水泥</div>
            </div>
          </div>
        </div>
        <a-modal v-model:visible="enterpriseLayerConfigModalVisible" centered :footer="null">
          <template #title> 企业分布 </template>
          <div style="display: flex;flex-direction: column;justify-content: center;align-items: center">
            <a-space>
              <div>显示内容:</div>
              <a-checkbox v-model:checked="layerConfig.enterpriseLogoShow">企业Logo</a-checkbox>
              <a-checkbox v-model:checked="layerConfig.enterpriseShortNameShow">企业简称</a-checkbox>
              <a-checkbox v-model:checked="layerConfig.enterpriseCapacityShow">产能</a-checkbox>
            </a-space>
          </div>
        </a-modal>
  
        <a-modal v-model:visible="priceSystemConfigModalVisible" centered :footer="null" :width="560">
          <template #title> 价格体系 </template>
          <div>
            <a-form layout="horizontal" :label-col="{style: {width: '10em'}}">
              <a-form-item label="水泥品种">
                <a-select disabled v-model:value="priceSystemConfig.cementAndPackageType" :options="cementAndPackageTypeList"> </a-select>
              </a-form-item>
              <a-form-item label="锚定中心">
                <a-radio-group v-model:value="priceSystemConfig.anchoringCenter" :options="anchoringCenterList"></a-radio-group>
              </a-form-item>
              <a-form-item label="显示内容">
                <div>
                  <a-checkbox-group v-model:value="priceSystemConfig.showContent">
                    <a-checkbox value="priceDiff">与锚定中心价差（到位价）</a-checkbox>
                    <a-checkbox value="price">标准价差（到位价）</a-checkbox>
                  </a-checkbox-group>
                  <a-checkbox v-model:checked="priceSystemConfig.hideContentWhenNone">均无数据时隐藏面板</a-checkbox>
                </div>
              </a-form-item>
              <a-form-item label="价差异常预警提示">
                <a-select v-model:value="priceSystemConfig.showPriceDiffAlert">
                  <a-select-option value="true">打开</a-select-option>
                  <a-select-option value="false">关闭</a-select-option>
                </a-select>
              </a-form-item>
              <a-form-item label="是否体现价差层级">
                <a-select disabled v-model:value="priceSystemConfig.showPriceDiffHierarchy">
                  <a-select-option value="true">是</a-select-option>
                  <a-select-option value="false">否</a-select-option>
                </a-select>
                <div style="display: flex;flex-direction: row;gap:2px;padding-top: 8px;">
                  <div v-for="item in priceDiffColorList" style="flex:1;height: 20px;" :style="{background: item}"> </div>
                </div>
              </a-form-item>
            </a-form>
          </div>
        </a-modal>
  
        <a-modal v-model:visible="simulateModalVisible" title="模拟调价" centered :width="560" @ok="handleSimulate">
          <a-form layout="horizontal" :label-col="{style: {width: '10em'}}">
            <a-form-item label="水泥品种" required>
              <a-select disabled v-model:value="simulateConfig.cementAndPackageType" :options="cementAndPackageTypeList"> </a-select>
            </a-form-item>
            <a-form-item label="锚定中心" required>
              <a-radio-group v-model:value="simulateConfig.anchoringCenter" :options="anchoringCenterList" @change="handleSimulateConfigAnchoringCenterChange"></a-radio-group>
            </a-form-item>
            <a-form-item label="当前最新到位价">
              <a-input-number disabled v-model:value="simulateConfig.latestPrice" style="width:100%;">
                <template #addonAfter>元/吨</template>
              </a-input-number>
              <template #extra> 当前最新到位价日期为{{simulateConfig.latestPriceDate}} </template>
            </a-form-item>
            <a-form-item label="调整后到位价" required>
              <a-input-number v-model:value="simulateConfig.price" style="width:100%;" :min="0" :precision="2">
                <template #addonAfter>元/吨</template>
              </a-input-number>
            </a-form-item>
          </a-form>
        </a-modal>
        <!-- end vid_xjg6gqqxpp 自定义模板_h1df8suis4 -->
      </a-spin>
    </div>
  </template>
  <script setup lang="tsx">
    import {
        h, ref, reactive, toRaw, markRaw, watch, computed,
        onBeforeMount, onMounted, onBeforeUnmount, onUnmounted, onActivated, onDeactivated
      } from "vue";
      import { useRoute, useRouter } from 'vue-router';
      const router = useRouter();
      const route = useRoute();
      import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios';
      import { cloneDeep, localGet, merge, getDifferenceArray, traversalTreeStructure, checkCaseCondition, renderStringInTemplate, handleBreadcrumbJump, throttle, permission, getComponentParamsValue } from '@/utils/index';
      import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is';
      import dayjs from 'dayjs';
      import { getPagePcChartsDataSourceConvert } from '@/utils/chart';
      import { message, notification, Modal } from 'ant-design-vue'
      import { propertyFormatByNumber, propertyFormatByPercentage, propertyFormatByDate, parseSubFromDataList } from '@/utils/format';
      import colorTheme from '@/design/custom-theme.json';
      /*** PUBLISH_EXEGESIS ***
      import UserTableRecords from '@/model/UserTableRecords';
      import { getAppBaseUrl } from '@/utils/index';
      import { sendToken } from "@/hooks/useIframeToken";
      import { useSystemStore } from "@/store/modules/system";
      const systemStore = useSystemStore();
      *** PUBLISH_EXEGESIS ***/
  
  
  
        // 获取传入的流程ID和组件参数
        const props = defineProps({
              'processInstanceId': {
              type: [String,Number,Boolean],
              default: undefined,
          },
        })
        const immediateWatch = (source, callback) => {
          watch(source, callback, {deep: true,immediate: true })
        }
  
  
  
    /* -------------------------- 属性定义 -------------------------- */
  
        const setTimeOutList = [];
        const pageLoading = reactive({
          loading: false,
          tip: undefined
        });
        const authInfo = localGet('app-user-store');
  
  
  
  
        // 处理校验
        const setSubFormName =(parentInfo, name)=>{
          return [parentInfo.parents, parentInfo.cycleIndex, name];
        }
  
  
    /* ========================== 属性定义 ========================== */
  
  
    /* -------------------------- 元素数据引用 -------------------------- */
  
  
    /* ========================== 元素数据引用 ========================== */
  
  
    /* -------------------------- 页面数据 -------------------------- */
  
  
    /* ========================== 页面数据 ========================== */
  
  
  
    /* -------------------------- 响应 -------------------------- */
  
    /* ========================== 响应 ========================== */
  
  
    /* -------------------------- 函数 -------------------------- */
  
    /* ========================== 函数 ========================== */
  
  
    /* -------------------------- 页面参数 -------------------------- */
  
      const pageParameter_state = reactive({
          'processInstanceId': props.processInstanceId ?? route.query.processInstanceId,
      })
  
    /* ========================== 页面参数 ========================== */
  
  
    /* -------------------------- 组件事件处理方法 -------------------------- */
  
      // ---------------------------- 组件数据同步 ----------------------------
  
      // ============================ 组件数据同步 ============================
  
  
    /* ========================== 组件事件处理方法 ========================== */
  
  
    /* -------------------------- 生命周期 -------------------------- */
    // 用于参数变更后重新执行自定义指令
        const queryUpdateFlag = ref(0);
        onMounted(() => { ;
  
      });
  
      onUnmounted(() => {
        // 销毁定时器
        setTimeOutList.forEach(({ repeat, timer }) => {
          repeat ?  clearInterval(timer): clearTimeout(timer);
        });
      });
  
    /* ========================== 生命周期 ========================== */
  
  
    /* -------------------------- 数据关联处理 -------------------------- */
  
  
  
  
  
    /* -------------------------- 表单数据同步 -------------------------- */
    /* ========================== 表单数据同步 ========================== */
  
    /* ========================== 数据关联处理 ========================== */
  
  
    /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */
  
    /* ========================== 不同组件自定义的处理逻辑 ========================== */
  
  
    // ================================定制化逻辑========================================
    window._AMapSecurityConfig = {
        securityJsCode: "37a7e520e06bc202ff267a6a0e492d13",
    };
    import AMapLoader from "@amap/amap-jsapi-loader";
  
    const logoSize = {
        markerPng: 'width: 24px;height: 24px;',
        '北方水泥': 'width: 16px;height: 16px;',
        '亚泰水泥': 'width: 24px;height: 12px',
        '金隅冀东': 'width: 19.5px;height: 12px',
        '蒙西水泥': 'width: 22px;height: 8px;',
        '山水水泥': 'width: 24px;height:16px',
        '天瑞水泥': 'width: 16px;height: 22px',
        '大鹰水泥': 'width: 24px;height: 10px',
        '海螺水泥': 'width: 32px;height: 8px'
    }
    const logoMap = {
        markerPng: '',
        '北方水泥': '',
        '亚泰水泥': '',
        '金隅冀东': '',
        '蒙西水泥': '',
        '山水水泥': '',
        '天瑞水泥': '',
        '大鹰水泥': '',
        '海螺水泥': ''
    }
  
    const viewType = ref('marketArea')
    const changeViewType = (type) =>{
        if(viewType.value === type) {
            return;
        }
        viewType.value = type;
        refreshMap()
    }
  
    const searchForm = reactive({
        regionInfo: null,
        provinceCode: null,
        cityCode: null,
  
        marketCenterId: null,
        marketDepartmentId: null,
        marketAreaId: null,
  
        enterpriseId: null,
    })
    const districtData = new Map();
    const loadDistrictData = () => {
        return get("/dynamic-price/api/v1/static_resources/463538588126978048").then((resp) => {
            // 提取全部曲线数据
            resp.forEach((item) => {
                item.features.forEach((feature) => {
                    feature.properties.adcode = feature.properties.code
                    districtData.set("" + feature.properties.code, feature);
                });
            });
        });
    };
    const mergeBoundary = (codes) => {
        let result = codes
                .map((code) => {
                    let feature = districtData.get("" + code);
                    let coordinates = feature?.geometry?.coordinates;
                    return coordinates;
                })
                .flatMap((item) => item)
                .filter((item) => item !== null && item !== undefined);
        return result;
    };
    const calcCenter = (areas) => {
        let size = areas.length;
        if (size <= 0) {
            return [];
        }
        let lngSum = 0;
        let latSum = 0;
        areas.forEach((item) => {
            lngSum += item[0];
            latSum += item[1];
        });
        let result = [lngSum / size, latSum / size];
        return result;
    };
  
    // 加载省份和地市数据
    const cityProvinceCodeMap = {}
    const provinceData = ref([])
    const loadProvinceData = () => {
        return post('/dynamic-price/api/v1/region_info/tree',{}).then(resp => {
            provinceData.value = (resp.data ?? []).map(p => {
                provinceCodeList.push(p.code)
                return {
                    ...p,
                    value: p.code,
                    label: p.name,
                    children: (p.children ?? []).map(c => {
                        cityCodeList.push(c.code);
                        cityProvinceCodeMap[c.code] = p.code;
                        (c.children ?? []).forEach(county => {
                            countyCodeList.push(county.code)
                        })
                        let cityInfo = {
                            ...c,
                            value: c.code,
                            label: c.name
                        }
                        delete cityInfo.children
                        return cityInfo
                    })
                }
            })
        })
    }
    const administrativeLayer = ref('city')
    const provinceSearchOptions = computed(() => {
        return (provinceData.value ?? []).map(item => {
            return {
                value: item.code,
                label: item.name
            }
        })
    })
    const handleProvinceChange = () => {
        map?.setCity(searchForm.provinceCode)
    }
  
    const citySearchOptions = computed(() => {
        return (provinceData.value ?? []).flatMap(item => {
            return item.children ?? []
        }).map(item => {
            return {
                value: item.code,
                label: item.name
            }
        })
    })
    const handleCityChange = () => {
        map?.setCity(searchForm.cityCode)
    }
  
    watch(
            () => administrativeLayer.value,
            () => {
                showProvinceLayer()
                showCityLayer()
                showAdministrativeMarkerLayer()
            }
    )
  
    // 加载销售区数据
    const marketAreaData = ref([])
    const loadMarketArea = () => {
        return get('/dynamic-price/api/v1/market_area/tree').then(resp => {
            marketAreaData.value = (resp.data ?? []).map(mc => {
                return {
                    ...mc,
                    value: 'mc__'+ mc.id,
                    label: mc.name,
                    children: (mc.children ?? []).map(md => {
                        return {
                            ...md,
                            value: 'md__'+ md.id,
                            label: md.name,
                            children: (md.children ?? []).map(ma => {
                                return {...ma,value: 'ma__' + ma.id,label: ma.name}
                            })
                        }
                    })
                }
            })
        })
    }
  
    // 修改销售区域
    const handleMarketCenterChange = () => {
        allMarketCenters.forEach(item => {
            if(item.id === searchForm.marketCenterId) {
                map?.setZoomAndCenter(7,item.feature.properties.center)
            }
        })
    }
    const handleMarketDepartmentChange = () => {
        allMarketDepartments.forEach(item => {
            if(item.id === searchForm.marketDepartmentId) {
                map?.setZoomAndCenter(10,item.feature.properties.center)
            }
        })
    }
    const handleMarketAreaChange = () => {
        allAreas.forEach(item => {
            if(item.id === searchForm.marketAreaId) {
                map?.setZoomAndCenter(11,item.feature.properties.center)
            }
        })
    }
  
  
    // 全部企业信息
    const enterpriseList = ref([])
    // 加载企业信息
    const loadEnterpriseList = () => {
        return get('/dynamic-price/api/v1/sand_map/enterprise_data').then(resp => {
            enterpriseList.value = (resp.data ?? []).map(item => {
                let logo = logoMap[item.groupName]
                let size = logoSize[item.groupName] ?? 'width: 24px'
                let logoContent = ''
                let groupEnterprise = true
                if (logo) {
                    logoContent = `<img src="${logo}" class="icon" style="${size}" alt=""/>`
                } else {
                    // 其它
                    groupEnterprise = false
                    logoContent = `<span style="width:10px;height:10px;display:block;background: #262626;border-radius: 50%">&nbsp;</span>`
                }
                if (item.enterpriceType === '窑磨一体' && item.classify === '内部企业') {
                    logoContent = `<img src="${logoMap.markerPng}" class="icon" style="width: 24px;height: 24px;" alt=""/>`
                }
                return {
                    ...item,
                    logo: logoContent,
                    groupEnterprise: groupEnterprise,
                    label: item.enterpriseShortName,
                    value: item.id
                }
            })
        })
    }
    // 处理企业信息变动
    const handleEnterpriseChange = () => {
        // 聚焦到选中的企业
        let selectedEnterprise = null;
        enterpriseList.value.forEach(item => {
            if(item.id === searchForm.enterpriseId) {
                selectedEnterprise = item;
            }
        })
        if(selectedEnterprise) {
            map?.setZoomAndCenter(12,[selectedEnterprise.longitude,selectedEnterprise.latitude])
        }
    }
  
    const cementAndPackageTypeList = ref([])
    const loadCementTypeAndPackageType = () => {
        return get('/dynamic-price/api/v1/base_info/union_cement_and_pack_type/list').then(resp => {
            cementAndPackageTypeList.value = (resp?.data ?? []).map(item => {
                return {
                    label: item,
                    value: item
                }
            })
        })
    }
  
    // 加载全部锚定中心
    const anchoringCenterList = ref([])
    const loadAnchoringCenterList = () => {
        return get('/dynamic-price/api/v1/market_area/anchoring_center_options').then(resp => {
            anchoringCenterList.value = (resp.data ?? []).map(item => {
                if(item.anchoringCenterName.indexOf('长春') > -1) {
                    priceSystemConfig.anchoringCenter = item.anchoringCenterId
                    simulateConfig.anchoringCenter = item.anchoringCenterId
                }
                return {
                    value: item.anchoringCenterId,
                    label: item.anchoringCenterName
                }
            })
            if(priceSystemConfig.anchoringCenter === null) {
                priceSystemConfig.anchoringCenter = item.anchoringCenterId
            }
            if(simulateConfig.anchoringCenter === null) {
                simulateConfig.anchoringCenter = item.anchoringCenterId
            }
        })
    }
  
    const layerConfig = reactive({
        // 企业图层是否展示
        enterpriseLayerShow: true,
        // 企业logo
        enterpriseLogoShow: true,
        // 企业简称
        enterpriseShortNameShow: false,
        // 产能
        enterpriseCapacityShow: false,
        // 价格体系
        priceSystemLayerShow: true,
        // 熟料库存&库容比
        inventoryLayerShow: true,
        // 市场销量&北方市占率
        salesVolumeLayerShow: true,
    })
  
    const enterpriseLayerConfigModalVisible = ref(false)
    const showEnterpriseLayerConfigModal = ()=> {
        enterpriseLayerConfigModalVisible.value = true
    }
    const priceSystemConfigModalVisible = ref(false)
    const showPriceSystemConfigModal = () => {
        priceSystemConfigModalVisible.value = true
    }
    const priceDiffColorList = [
        '#67E683','#95EEA8','#C2F5CD','#E5F6FF',
        '#FFBEBE','#FF8D8D','#FF5959'
    ]
    const colorList = [
        '#CFEAFF','#B5EDEB','#BAEDB5','#D9E7AC',
        '#FCF9C4','#FDE8D7','#FFD4CA',
    ]
    const priceSystemConfig = reactive({
        cementAndPackageType: 'P·O42.5水泥散装',
        // 锚定中心
        anchoringCenter:null,
        // 显示内容
        showContent: ['priceDiff', 'price'],
        // 均无数据时隐藏面板
        hideContentWhenNone: true,
        // 价差异常预警提示
        showPriceDiffAlert: 'true',
        // 是否体现价差层级
        showPriceDiffHierarchy: 'false',
    })
  
    let AMap = null;
    let loca = null;
    let map = null;
    const currentZoom = ref(6.2)
    // 初始化地图
    const initMap = () => {
        return AMapLoader.load({
            key: "09b7ca63fd0a1ac64f96409c63347962", // 申请好的Web端开发者Key，首次调用 load 时必填
            version: "2.0", // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
            plugins: ["Map3D", "AMap.DistrictSearch", "AMap.Geocoder"], //需要使用的的插件列表，如比例尺'AMap.Scale'，支持添加多个如：['...','...']
            Loca: {
                // 是否加载 Loca， 缺省不加载
                version: "2.0.0", // Loca 版本，缺省 1.3.2
            },
        }).then((AMapInstancec) => {
            AMap = AMapInstancec;
            map = new AMap.Map("MapContainer", {
                mapStyle: "amap://styles/whitesmoke",
                viewMode: "2D",
                pitch: 0,
                zoom: 6.2,
                center: [125.662394,46.544135],
            });
            loca = window.loca = new Loca.Container({
                map: map,
            });
            map.on('complete', () => {
                // 地图加载完成
                currentZoom.value = map.getZoom()
                refreshMap()
            })
            // 缩放后刷新地图
            map.on('zoomend', () => {
                currentZoom.value = map.getZoom()
                refreshMap();
            })
            // 拖拽后，刷新地图
            map.on('moveend', () => {
                refreshEnterpriseLayer()
                showAdministrativeMarkerLayer()
                showPriceSystemLayer()
            })
        })
    }
    onUnmounted(() => {
        map?.destroy();
    });
    // 企业信息图层
    const legendShow = computed(() => {
        if(!layerConfig.enterpriseLayerShow) {
            return false
        }
        if(!layerConfig.enterpriseLogoShow) {
            // 企业相关信息均不显示
            return false;
        }
        return true
    })
    let enterpriseLayer = null;
    const refreshEnterpriseLayer = () => {
        if(enterpriseLayer === null) {
            // 初始化图层
            enterpriseLayer = new AMap.OverlayGroup([])
            map.add(enterpriseLayer)
        }
        // 清空地图上企业信息
        enterpriseLayer.clearOverlays()
  
        if(!layerConfig.enterpriseLayerShow) {
            return;
        }
        if(!layerConfig.enterpriseLogoShow &&!layerConfig.enterpriseShortNameShow &&!layerConfig.enterpriseCapacityShow) {
            // 企业相关信息均不显示
            return;
        }
        // 在视口内的企业
        let enterpriseInViewport = enterpriseList.value.filter(item => {
            let longitude = parseFloat(item.longitude)
            let latitude = parseFloat(item.latitude)
            if(isNaN(longitude) || isNaN(latitude)) {
                return false
            }
            return map.getBounds().contains(new AMap.LngLat(item.longitude, item.latitude))
        }).filter(item => {
            // 如果当前缩放层级小于7，则隐藏掉非集团的企业
            if(currentZoom.value > 7) {
                return true
            }
            return item.groupEnterprise
        })
  
        let enterpriseMarkers = enterpriseInViewport.map(enterprise => {
            let logoContent = '';
            if(layerConfig.enterpriseLogoShow) {
                // 处理logo
                logoContent = enterprise.logo
            }
            let nameContent = ''
            if(layerConfig.enterpriseShortNameShow && currentZoom.value > 7) {
                nameContent = '<span>' + enterprise.enterpriseShortName + '</span>'
            }
            let capacityContent1 = '';
            if(currentZoom.value > 7 && layerConfig.enterpriseCapacityShow && enterprise.capacityList) {
                for(let i = 0;i < enterprise.capacityList.length;i++) {
                    capacityContent1 += '<span style="display: inline-block;padding: 0 2px;">' + enterprise.capacityList[i] + "</span>"
                    if(layerConfig.enterpriseShortNameShow) {
                        if(i % 2 == 0) {
                            capacityContent1 += '<br/>'
                        }
                    } else {
                        if(i % 2 == 1) {
                            capacityContent1 += '<br/>'
                        }
                    }
                }
            }
  
            let content = `<div style="display: flex;flex-direction:row;color: #262626;line-height:16px;gap:4px;align-items: center">
          <div>${logoContent}</div>
          <div style="white-space: nowrap;">
              ${nameContent}${capacityContent1}
          </div>
      </div>`;
            return new AMap.Marker({
                position: [enterprise.longitude, enterprise.latitude],
                title: enterprise.name,
                content,
                extData: {
                    position: [enterprise.longitude, enterprise.latitude],
                    title: enterprise.name,
                    type: "enterprise",
                },
            })
        })
        enterpriseLayer.addOverlays(enterpriseMarkers)
    }
  
  
    // 行政区域 administrativeArea
    const districtInfo = {}
    const provinceCodeList = []
    const cityCodeList = []
    const countyCodeList = []
  
    let districtsLayerStyle = {
        'fill': function (properties) {
            var adcode = properties.adcode;
            return getColorByAdcode(adcode);
        },
        'stroke-width': (params) => {
            if(params.level === 'province') {
                return 2
            }
            return 1
        },
        'province-stroke': '#EF9999',
        'city-stroke': '#EF9999', // 中国地级市边界
        //'city-stroke': 'rgba(0,0,0,0.1)', // 中国地级市边界
        // 'city-stroke': '#FFFFFF', // 中国地级市边界
        // 'city-stroke': '#CECECE', // 中国地级市边界
        'county-stroke': '#EF9999' // 中国区县边界
    }
    const getColorByAdcode = (adcode) => {
        // 根据各行政区的到位加显示颜色
        // 如果code不在后端返回的行政区内。在显示为透明
        if(!provinceCodeList.includes('' + adcode) && !cityCodeList.includes('' + adcode)  && !countyCodeList.includes('' + adcode) ) {
            return 'rgba(0,0,0,0)'
        }
        if(cityCodeList.includes('' + adcode)) {
            adcode = cityProvinceCodeMap[adcode] ?? adcode
        }
        if(adcode === '150000' || adcode === 150000) {
            return '#D9E7AC'
        } else if(adcode === '210000' || adcode === 210000) {
            return '#D9EDF6'
        } else if(adcode === '220000' || adcode === 220000) {
            return '#FCF9C4'
        } else if(adcode === '230000' || adcode === 230000) {
            return '#FDE8D7'
        }
        let price = parseFloat(districtInfo['' + adcode]?.inventory);
        if(isNaN(price)) {
            price = 0;
        }
        let priceIndex = Math.floor(price * 100) % colorList.length
        priceIndex = Math.max(0, Math.min(priceIndex, colorList.length - 1))
        return colorList[priceIndex]
    }
  
    // 省份图层
    let provinceLayer = null;
    const showProvinceLayer = () => {
        if(provinceLayer === null) {
            provinceLayer = new AMap.DistrictLayer.Province({
                zIndex: 11,
                adcode: provinceCodeList,
                depth: 0,
                styles: districtsLayerStyle
            });
            provinceLayer.setMap(map);
        }
        let show = false
        if(viewType.value !== 'marketArea' && administrativeLayer.value === 'province') {
            show = true
        }
        if(show) {
            provinceLayer.show()
        } else {
            provinceLayer.hide()
        }
    }
    // 地级市地图
    let cityLayer = null;
    const showCityLayer = () => {
        if(cityLayer === null) {
            cityLayer = new AMap.DistrictLayer.Province({
                zIndex: 11,
                // zooms: [7,22],
                adcode: provinceCodeList,
                depth: 1,
                styles: districtsLayerStyle
            });
            cityLayer.setMap(map);
        }
        let show = false
        if(viewType.value !== 'marketArea'  && administrativeLayer.value === 'city') {
            show = true
        }
        if(show) {
            cityLayer.show()
        } else {
            cityLayer.hide()
        }
    }
  
    // 行政区域上的各种信息图层
    let administrativeMarkerLayer = null;
    const showAdministrativeMarkerLayer = () => {
        if(administrativeMarkerLayer === null) {
            administrativeMarkerLayer = new AMap.OverlayGroup()
            map.add(administrativeMarkerLayer)
        }
        administrativeMarkerLayer.clearOverlays()
        if(viewType.value === 'marketArea') {
            return;
        }
        if(!layerConfig.inventoryLayerShow && !layerConfig.salesVolumeLayerShow) {
            return;
        }
        if(administrativeLayer.value == 'province') {
            // 显示省级信息
            let markers = provinceData.value.map(item => {
                return createAdministrativeMarker(item)
            })
            administrativeMarkerLayer.addOverlays(markers)
        } else {
            // 显示地级市信息
            let markers = provinceData.value.flatMap(item => item.children)
                    .filter(item => {
                        return map.getBounds().contains(new AMap.LngLat(item.longitude, item.latitude))
                    }).map(item => {
                        return createAdministrativeMarker(item)
                    })
            administrativeMarkerLayer.addOverlays(markers)
        }
    }
    const createAdministrativeMarker = (item) => {
        let content = '<div style="background:#FFF;border-radius:2px;box-shadow: 0px 0px 4px rgba(0,0,0,0.2);white-space: nowrap;padding: 2px 8px;">';
        content += `<div style="font-weight: 600;">${item.name}</div>`
        if(layerConfig.inventoryLayerShow) {
            // 熟料库存&库容比
            let inventory = districtInfo[item.code]?.inventory ?? '-'
            let storageCapacityRatio = districtInfo[item.code]?.storageCapacityRatio ?? '-'
            content += `<div>库存：<span style="color: #D7000F;font-weight: 600;">${inventory}</span>；库容比：<span style="color: #D7000F;font-weight: 600;">${storageCapacityRatio}%</span></div>`
        }
        if(layerConfig.salesVolumeLayerShow) {
            // 市场销量&北方市占率
            let salesVolume = districtInfo[item.code]?.salesVolume ?? '-'
            let marketShare = districtInfo[item.code]?.marketShare ?? '-'
            content += `<div>销量：<span style="color: #D7000F;font-weight: 600;">${salesVolume}</span>；市占率：<span style="color: #D7000F;font-weight: 600;">${marketShare}%</span></div>`
        }
        content += '</div>'
  
        return new AMap.Marker({
            position: [item.longitude, item.latitude],
            title: item.name,
            content,
            anchor: 'top-center',
            offset: [0,20],
            zIndex: 16,
            extData: {
                position: [item.longitude, item.latitude],
                title: item.name,
            },
        })
    }
  
    const administrativeAreaInfo = reactive({})
    const loadAdministrativeAreaInfo = () => {
        return get('/dynamic-price/api/v1/sand_map/administration_region_data').then(resp => {
            Object.assign(administrativeAreaInfo, resp.data ?? {})
            ;(resp.data?.provinceDataList ?? []).forEach(item => {
                districtInfo[item.provinceCode] = {
                    ...item,
                    price: item.inventory
                }
            })
            ;(resp.data?.cityDataList ?? []).forEach(item => {
                districtInfo[item.cityCode] = {
                    ...item,
                    price: item.inventory
                }
            })
        })
    }
  
    // 营销区域
    const marketLayer = ref('marketArea')
  
    let allAreas = []
    let edges = {}
    // 加载全部区域数据
    const loadAllAreas = () => {
        return get('/dynamic-price/api/v1/market_area/all_with_area_list').then(resp => {
            allAreas = resp.data.map((item,index) => {
                let coordinates = mergeBoundary((item.areaInfoList ?? []).map((areaSub) => areaSub.code));
                if (coordinates.length <= 0) {
                    return null;
                }
                return {
                    id : item.marketArea.id,
                    name: item.marketArea.marketAreaName,
                    areaLists: item.areaInfoList.map(sub => sub.code),
  
                    // 将全部区域合并 boundary
                    feature: {
                        type: "Feature",
                        properties: {
                            color: colorList[index % colorList.length],
                            adcode: "" + item.marketArea.id,
                            name: item.marketArea.marketAreaName,
                            currentInPlacePriceDate: null,
                            currentInPlacePrice: null,
                            averageInPlacePrice: null,
                            currentInPlacePriceDiff: null,
                            averageInPlacePriceDiff: null,
                            center: calcCenter(item.areaInfoList.map((subArea) => [subArea.longitude, subArea.latitude])),
                        },
                        geometry: {
                            type: "MultiPolygon",
                            coordinates: coordinates,
                        },
                    }
                }
            }).filter(item => item != null)
        })
    }
    const loadAreaNearInfo = () => {
        return get('/dynamic-price/api/v1/market_area/near_region').then(resp => {
            resp.data.forEach(item => {
                edges[item.marketAreaId] = item.marketAreaNearRegionList.map(near => near.marketAreaId)
            })
        })
    }
    const refreshColor = () => {
        let colorsCount = {}
        colorList.forEach(c => colorsCount[c] = 0)
        let colorDataMap = {}
        let areaIdList = []
        allAreas.forEach(item => {
            colorDataMap[item.id] = null
            areaIdList.push(item.id)
        })
  
        // 使用简单回溯的方式进行染色
        const simpleBacktracking = (i) => {
            if(i>=areaIdList.length) {
                return true
            }
            let id = areaIdList[i]
            // 获取该节点可以上色的颜色列表
            let canUsedColors = [...colorList]
            // 该节点临近的节点列表
            let adjacentNodes = edges[id]
            adjacentNodes?.forEach(adjacentNode => {
                let nodeColor = colorDataMap[adjacentNode]
                if(nodeColor) {
                    canUsedColors = canUsedColors.filter(item => item !== nodeColor)
                }
            })
            // 如果可用颜色为null，则标识该路径尝试失败，需要上一个节点尝试回退
            if(canUsedColors.length <= 0) {
                // colorDataMap[id] = null
                // return false
                // TODO: 临近关系数据存在问题，导致染色失败
                colorDataMap[id] = colorList[0]
                return true;
            }
            // 逐个颜色尝试染色，
            while(canUsedColors.length > 0) {
                // 获取颜色使用次数最少的一个
                let c = null;
                let cc = null;
                canUsedColors.forEach(uc => {
                    if(c === null) {
                        cc = colorsCount[uc]
                        c = uc
                    } else {
                        if(cc > colorsCount[uc]) {
                            cc = colorsCount[uc]
                            c = uc
                        }
                    }
                })
                colorDataMap[id] = c
                colorsCount[c] = colorsCount[c] + 1
                let tryResult = simpleBacktracking(i+1)
                if(tryResult) {
                    return true
                }
                canUsedColors = canUsedColors.filter(item => item !== c)
                colorsCount[c] = colorsCount[c] - 1
                // 染色失败，回退当前节点
                colorDataMap[id] = null
            }
            // 全部颜色尝试均失败
            return false
        }
        // if(simpleBacktracking(0)) {
        //     allAreas.forEach(item => {
        //         item.feature.properties.color = colorDataMap[item.id]
        //     })
        // }
        allAreas.forEach(item => {
            item.feature.properties.color = colorList[item.id % colorList.length]
        })
    }
    // 市场部
    let allMarketDepartments = []
    let marketDepartmentEdges = {}
    const loadAllMarketDepartmentAreaInfo = () => {
        return get('/dynamic-price/api/v1/market_department/all_with_area_list').then(resp => {
            allMarketDepartments = resp.data.map((item,index) => {
                let coordinates = mergeBoundary((item.areaInfoList ?? []).map((areaSub) => areaSub.code));
                if (coordinates.length <= 0) {
                    return null;
                }
  
                return {
                    id : item.marketDepartment.id,
                    name: item.marketDepartment.name,
                    areaLists: item.areaInfoList.map(sub => sub.code),
  
                    // 将全部区域合并 boundary
                    feature: {
                        type: "Feature",
                        properties: {
                            color: colorList[index % colorList.length],
                            adcode: "" + item.marketDepartment.id,
                            name: item.marketDepartment.name,
                            currentInPlacePriceDate: null,
                            currentInPlacePrice: null,
                            averageInPlacePrice: null,
                            currentInPlacePriceDiff: null,
                            averageInPlacePriceDiff: null,
                            center: calcCenter(item.areaInfoList.map((item) => [item.longitude, item.latitude])),
                        },
                        geometry: {
                            type: "MultiPolygon",
                            coordinates: coordinates,
                        },
                    }
                }
            }).filter(item => item != null)
        })
    }
    const loadMarketDepartmentNearInfo = () => {
        return get('/dynamic-price/api/v1/market_department/near_region').then(resp => {
            resp.data.forEach(item => {
                marketDepartmentEdges[item.marketDepartmentId] = item.nearDepartmentList.map(near => near.marketDepartmentId)
            })
        })
    }
    const refreshMarketDepartmentColor = () => {
        let colorsCount = {}
        colorList.forEach(c => colorsCount[c] = 0)
        let colorDataMap = {}
        let areaIdList = []
        allMarketDepartments.forEach(item => {
            colorDataMap[item.id] = null
            areaIdList.push(item.id)
        })
  
        // 使用简单回溯的方式进行染色
        const simpleBacktracking = (i) => {
            if(i>=areaIdList.length) {
                return true
            }
            let id = areaIdList[i]
            // 获取该节点可以上色的颜色列表
            let canUsedColors = [...colorList]
            // 该节点临近的节点列表
            let adjacentNodes = marketDepartmentEdges[id]
            adjacentNodes?.forEach(adjacentNode => {
                let nodeColor = colorDataMap[adjacentNode]
                if(nodeColor) {
                    canUsedColors = canUsedColors.filter(item => item !== nodeColor)
                }
            })
            // 如果可用颜色为null，则标识该路径尝试失败，需要上一个节点尝试回退
            if(canUsedColors.length <= 0) {
                colorDataMap[id] = null
                return false
            }
            // 逐个颜色尝试染色，
            while(canUsedColors.length > 0) {
                // 获取颜色使用次数最少的一个
                let c = null;
                let cc = null;
                canUsedColors.forEach(uc => {
                    if(c === null) {
                        cc = colorsCount[uc]
                        c = uc
                    } else {
                        if(cc > colorsCount[uc]) {
                            cc = colorsCount[uc]
                            c = uc
                        }
                    }
                })
                colorDataMap[id] = c
                colorsCount[c] = colorsCount[c] + 1
                let tryResult = simpleBacktracking(i+1)
                if(tryResult) {
                    return true
                }
                canUsedColors = canUsedColors.filter(item => item !== c)
                colorsCount[c] = colorsCount[c] - 1
                // 染色失败，回退当前节点
                colorDataMap[id] = null
            }
            // 全部颜色尝试均失败
            return false
        }
        // if(simpleBacktracking(0)) {
        //     allMarketDepartments.forEach(item => {
        //         item.feature.properties.color = colorDataMap[item.id]
        //     })
        // }
        // allMarketDepartments.forEach(item => {
        //     item.feature.properties.color = colorList[item.id % colorList.length]
        // })
    }
  
    // 营销中心
    let allMarketCenters = []
    let marketCenterEdges = {}
    const loadAllMarketCenterAreaInfo = () => {
        return get('/dynamic-price/api/v1/market_center/all_with_area_list').then(resp => {
            allMarketCenters = resp.data.map((item,index) => {
                let coordinates = mergeBoundary((item.areaInfoList ?? []).map((areaSub) => areaSub.code));
                if (coordinates.length <= 0) {
                    return null;
                }
  
                return {
                    id : item.marketCenter.id,
                    name: item.marketCenter.name,
                    areaLists: item.areaInfoList.map(sub => sub.code),
  
                    // 将全部区域合并 boundary
                    feature: {
                        type: "Feature",
                        properties: {
                            color: colorList[index % colorList.length],
                            adcode: "" + item.marketCenter.id,
                            name: item.marketCenter.name,
                            currentInPlacePriceDate: null,
                            currentInPlacePrice: null,
                            averageInPlacePrice: null,
                            currentInPlacePriceDiff: null,
                            averageInPlacePriceDiff: null,
                            center: calcCenter(item.areaInfoList.map((item) => [item.longitude, item.latitude])),
                        },
                        geometry: {
                            type: "MultiPolygon",
                            coordinates: coordinates,
                        },
                    }
                }
            }).filter(item => item != null)
        })
    }
    const loadMarketCenterNearInfo = () => {
  
    }
  
    let marketAreaPolygonLayer = null;
    const showMarketAreaLayer = () => {
        if(viewType.value !== 'marketArea' || marketLayer.value !== 'marketArea') {
            marketAreaPolygonLayer?.hide()
            return;
        }
        if(marketAreaPolygonLayer === null) {
            marketAreaPolygonLayer = new Loca.PolygonLayer({
                zIndex: 120,
                opacity: 1,
                shininess: 10,
                // zooms: [10,22],
                hasSide: false,
                acceptLight: false,
                labelsLayerOptions: {
                    opacity: 1,
                    visible: true,
                },
            });
            loca.add(marketAreaPolygonLayer);
  
            marketAreaPolygonLayer.setSource(
                    new Loca.GeoJSONSource({
                        data: {
                            type: "FeatureCollection",
                            features: allAreas.map(item => item.feature),
                        },
                    })
            );
            marketAreaPolygonLayer.setStyle({
                topColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                sideTopColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                sideBottomColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                height: function (index, feature) {
                    return 10;
                },
                label: {
                    text: {
                        content: (index, feat) => {
                            return "" + feat.properties.name;
                        },
                        style: {
                            fillColor: "#6b6b6b",
                            strokeColor:'#FFFFF',
                        },
                    },
                },
                altitude: 0,
            });
  
        }
  
        marketAreaPolygonLayer?.show()
    }
  
    let marketDepartmentPolygonLayer = null;
    const showMarketDepartmentLayer = () => {
        if(viewType.value !== 'marketArea' || marketLayer.value !== 'marketDepartment') {
            marketDepartmentPolygonLayer?.hide()
            return;
        }
        if(marketDepartmentPolygonLayer === null) {
            marketDepartmentPolygonLayer = new Loca.PolygonLayer({
                zIndex: 120,
                opacity: 1,
                shininess: 10,
                // zooms: [7,10],
                hasSide: false,
                acceptLight: false,
                labelsLayerOptions: {
                    opacity: 1,
                    visible: true,
                },
            });
            loca.add(marketDepartmentPolygonLayer);
  
            marketDepartmentPolygonLayer.setSource(
                    new Loca.GeoJSONSource({
                        data: {
                            type: "FeatureCollection",
                            features: allMarketDepartments.map(item => item.feature),
                        },
                    })
            );
            marketDepartmentPolygonLayer.setStyle({
                topColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                sideTopColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                sideBottomColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                height: function (index, feature) {
                    return 10;
                },
                label: {
                    text: {
                        content: (index, feat) => {
                            return "" + feat.properties.name;
                        },
                        style: {
                            fillColor: "#6b6b6b",
                            strokeColor:'#FFFFF',
                        },
                    },
                },
                altitude: 0,
            });
  
        }
  
        marketDepartmentPolygonLayer?.show()
    }
  
    let marketCenterPolygonLayer = null;
    const showMarketCenterLayer = () => {
        if(viewType.value !== 'marketArea' || marketLayer.value !== 'marketCenter') {
            marketCenterPolygonLayer?.hide()
            return;
        }
        if(marketCenterPolygonLayer === null) {
            marketCenterPolygonLayer = new Loca.PolygonLayer({
                zIndex: 120,
                opacity: 1,
                shininess: 10,
                // zooms: [2,7],
                hasSide: false,
                acceptLight: false,
                labelsLayerOptions: {
                    opacity: 1,
                    visible: true,
                },
            });
            loca.add(marketCenterPolygonLayer);
  
            marketCenterPolygonLayer.setSource(
                    new Loca.GeoJSONSource({
                        data: {
                            type: "FeatureCollection",
                            features: allMarketCenters.map(item => item.feature),
                        },
                    })
            );
            marketCenterPolygonLayer.setStyle({
                topColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                sideTopColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                sideBottomColor: function (index, feature) {
                    return feature.properties.color ?? colorList[0];
                },
                height: function (index, feature) {
                    return 10;
                },
                label: {
                    text: {
                        content: (index, feat) => {
                            return "" + feat.properties.name;
                        },
                        style: {
                            fillColor: "#6b6b6b",
                            strokeColor:'#FFFFF',
                        },
                    },
                },
                altitude: 0,
            });
  
        }
  
        marketCenterPolygonLayer?.show()
    }
  
    watch(
            () => marketLayer.value,
            () => {
                showMarketAreaLayer()
                showMarketDepartmentLayer()
                showMarketCenterLayer()
                showPriceSystemLayer()
            }
    )
    const marketCenterSearchOptions = computed(() => {
        return (marketAreaData.value ?? []).map(item => {
            return {
                value: item.id,
                label: item.name
            }
        })
    })
    const marketDepartmentSearchOptions = computed(() => {
        return (marketAreaData.value ?? []).flatMap(item => item.children ?? []).map(item => {
            return {
                value: item.id,
                label: item.name
            }
        })
    })
    const marketAreaSearchOptions = computed((() => {
        return (marketAreaData.value ?? [])
                .flatMap(item => item.children ?? [])
                .flatMap(item => item.children ?? [])
                .map(item => {
                    return {
                        value: item.id,
                        label: item.name
                    }
                })
    }))
  
    const refreshMap = () => {
        // 刷新地图
        refreshEnterpriseLayer()
        showProvinceLayer()
        showCityLayer()
        showAdministrativeMarkerLayer()
  
        showMarketAreaLayer()
        showMarketDepartmentLayer()
        showMarketCenterLayer()
        showPriceSystemLayer()
    }
    watch(
            () => layerConfig,
            () => {
                refreshMap()
            }, {
                deep: true
            }
    )
  
    const priceSystemData = ref([])
    const simulating = ref(false)
    const loadPriceSystemData = () => {
        if(simulating.value) {
            // 模拟，请求模拟接口
            return post('/dynamic-price/api/v1/sand_map/mock_adjust_price', {
                "cementTypeAndPackType": priceSystemConfig.cementAndPackageType,
                "anchoringCenterId": priceSystemConfig.anchoringCenter,
                "mockAdjustPriceCementTypeAndPackType": simulateConfig.cementAndPackageType,
                "mockAdjustPriceAnchoringCenterId": simulateConfig.anchoringCenter,
                "currentPrice": simulateConfig.latestPrice,
                "adjustedPrice": simulateConfig.price
            }).then(resp => {
                priceSystemData.value = (resp.data ?? []).map(item => {
                    // 查找销售区域中心位置
                    let center = null;
                    allAreas.forEach(areaItem => {
                        if(areaItem.id === item.marketAreaId) {
                            center = areaItem.feature.properties.center
                        }
                    })
                    return {
                        ...item,
                        center: center
                    }
                })
            }).then(() => {
                showPriceSystemLayer()
            })
        } else {
            return post('/dynamic-price/api/v1/sand_map/market_area_price', {
                cementTypeAndPackType: priceSystemConfig.cementAndPackageType,
                anchoringCenterId: priceSystemConfig.anchoringCenter
            }).then(resp => {
                priceSystemData.value = (resp.data ?? []).map(item => {
                    // 查找销售区域中心位置
                    let center = null;
                    allAreas.forEach(areaItem => {
                        if(areaItem.id === item.marketAreaId) {
                            center = areaItem.feature.properties.center
                        }
                    })
                    return {
                        ...item,
                        center: center
                    }
                })
            }).then(() => {
                showPriceSystemLayer()
            })
        }
    }
    let priceSystemLayer = null;
    const showPriceSystemLayer = () => {
        // 绘制价格体系图层
        if(!map) {
            // 地图未初始化，直接返回
            return;
        }
        if(!priceSystemLayer) {
            priceSystemLayer = new AMap.OverlayGroup()
            map.add(priceSystemLayer)
        }
        priceSystemLayer.clearOverlays()
        if(viewType.value !== 'marketArea') {
            return;
        }
        // 什么信息都不展示
        if(!layerConfig.priceSystemLayerShow || !priceSystemConfig.showContent || priceSystemConfig.showContent.length <= 0) {
            return
        }
        // 当前只显示市场区域维度，选择市场部和营销中心时，不显示
        if(marketLayer.value !== 'marketArea') {
            return;
        }
        let data = priceSystemData.value.filter(item => {
            let longitude = parseFloat(item?.center?.[0])
            let latitude = parseFloat(item?.center?.[1])
            if(!isNaN(longitude) && !isNaN(latitude)) {
                return map.getBounds().contains(new AMap.LngLat(longitude, latitude))
            }
            return false
        })
  
        let markets = data.map(item => {
            let longitude = parseFloat(item?.center?.[0])
            let latitude = parseFloat(item?.center?.[1])
            let content = ''
            if(item.marketAreaId === priceSystemConfig.anchoringCenter) {
                // 锚定中心的样式
                content = '<div style="width: 116px; height: 56px; border-radius: 2px; border: 1px solid rgba(215,0,15,0.6); background: #FFF; box-shadow: 0 0 4px rgba(0,0,0,0.2);">' +
                        '<div style="display: flex;flex-direction:row;justify-content: center;align-items: center;width: 116px; height: 56px; ">'
                content += '<img style="width:24px;height:24px;" src=""/>'
  
                let priceDiffContent = null;
  
                if(priceSystemConfig.showContent.indexOf('priceDiff') > -1) {
                    let currentInPlacePriceDiff = parseFloat(item.currentInPlacePriceDiff)
                    if(isNaN(currentInPlacePriceDiff)) {
                        priceDiffContent = `<span style="font-weight: 600;" class="priceDiff">-</span>`
                    } else {
                        priceDiffContent = `<span style="font-weight: 600;" class="priceDiff">${currentInPlacePriceDiff}</span>`
  
                    }
                }
                let priceContent = null;
  
                if(priceSystemConfig.showContent.indexOf('price') > -1) {
                    let currentInPlacePrice = parseFloat(item.currentInPlacePrice)
                    if(isNaN(currentInPlacePrice)) {
                        priceContent = `<span style="font-weight: 600;" class="price">-</span>`
                    } else {
                        priceContent = `<span class="price">￥<span style="font-weight: 600;">${currentInPlacePrice}</span></span>`
  
                    }
                }
  
                let allContent = [priceDiffContent,priceContent].filter(item => item != null).join(';');
  
                content += `
      <div>
                  <div>锚定中心</div>
                  <div style="font-weight: 600">${allContent}</div>
      </div>
                  `
                content += '</div></div>'
            } else {
  
                let currentPriceDiffContent = null;
                let currentPriceDiffIsNull = true
                if (priceSystemConfig.showContent.indexOf('priceDiff') > -1) {
                    let currentInPlacePriceDiff = parseFloat(item.currentInPlacePriceDiff)
                    let diffContent = ''
                    if (isNaN(currentInPlacePriceDiff)) {
                        diffContent = `<span style="font-weight: 600;" class="priceDiff">-</span>`
                    } else if (currentInPlacePriceDiff < 0) {
                        diffContent = `<span class="priceDiff" style="font-weight: 600;color:#30BF78">${currentInPlacePriceDiff}</span>`
                        currentPriceDiffIsNull = false
                    } else if (currentInPlacePriceDiff > 0) {
                        diffContent = `<span class="priceDiff" style="font-weight: 600;color:#D7000F">${currentInPlacePriceDiff}</span>`
                        currentPriceDiffIsNull = false
                    } else {
                        diffContent = `<span style="font-weight: 600;" class="priceDiff">${currentInPlacePriceDiff}</span>`
                        currentPriceDiffIsNull = false
                    }
                    let currentInPlacePrice = parseFloat(item.currentInPlacePrice)
                    let priceContent = ''
                    if (isNaN(currentInPlacePrice)) {
                        priceContent = '<span style="color:#3875FF">(-)</span>'
                    } else {
                        priceContent = `<span style="color:#3875FF">(￥${currentInPlacePrice})</span>`
                    }
                    currentPriceDiffContent = `<div>当前: ${diffContent}${priceContent}</div>`
                }
  
  
                let standardInPlacePriceDiffContent = null;
                let standardPriceDiffIsNull = true
                if (priceSystemConfig.showContent.indexOf('price') > -1) {
                    let standardInPlacePriceDiff = parseFloat(item.standardInPlacePriceDiff)
                    let diffContent = ''
                    if (isNaN(standardInPlacePriceDiff)) {
                        diffContent = `<span style="font-weight: 600;" class="price">-</span>`
                    } else if (standardInPlacePriceDiff < 0) {
                        diffContent = `<span class="price" style="font-weight: 600;color:#30BF78">${standardInPlacePriceDiff}</span>`
                        standardPriceDiffIsNull = false
                    } else if (standardInPlacePriceDiff > 0) {
                        diffContent = `<span class="price" style="font-weight: 600;color:#D7000F">${standardInPlacePriceDiff}</span>`
                        standardPriceDiffIsNull = false
                    } else {
                        diffContent = `<span style="font-weight: 600;" class="price">${standardInPlacePriceDiff}</span>`
                        standardPriceDiffIsNull = false
                    }
                    let standardInPlacePrice = parseFloat(item.standardInPlacePrice)
                    let priceContent = ''
                    if (isNaN(standardInPlacePrice)) {
                        priceContent = '<span style="color:#3875FF">(-)</span>'
                    } else {
                        priceContent = `<span style="color:#3875FF">(￥${standardInPlacePrice})</span>`
                    }
                    standardInPlacePriceDiffContent = `<div>标准: ${diffContent}${priceContent}</div>`
                }
                let allContent = [currentPriceDiffContent, standardInPlacePriceDiffContent].filter(item => item != null).join('');
  
                if (priceSystemConfig.hideContentWhenNone && standardPriceDiffIsNull && currentPriceDiffIsNull) {
                    return null;
                }
                // 告警
                let alarmContent = ''
                if(priceSystemConfig.showPriceDiffAlert === 'true') {
                    // 打开，显示告警信息
                    if(item.alarm) {
                        alarmContent = '<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"><circle cx="15" cy="15" r="2" stroke="red" stroke-width="6" fill="none"><animate attributeName="r" from="2" to="12" dur="2s" repeatCount="indefinite" /><animate attributeName="stroke-opacity" from="1" to="0" dur="2s" repeatCount="indefinite" /></circle></svg>'
                    }
                }
  
                content = `<div style="display: flex;flex-direction:column;color: #262626;line-height:18px;white-space: nowrap;background:#FFF;padding: 8px;box-shadow: 0px 0px 4px 0px rgba(0,0,0,0.2);">
    <div style="font-weight: 600;display: flex;flex-direction: row;align-items: center;">${item.marketAreaName}${alarmContent}</div>
    ${allContent}
    </div>`;
            }
  
            return new AMap.Marker({
                position: [longitude, latitude],
                anchor: 'center',
                title: item.marketAreaName,
                content,
                zIndex: 20,
                extData: {
                    position: [longitude, latitude],
                    title: item.marketAreaName,
                },
            })
        }).filter(item => item != null)
        priceSystemLayer.addOverlays(markets)
    }
  
    watch(
            () => priceSystemConfig,
            () => {
                loadPriceSystemData()
            }, {
                deep: true
            }
    )
  
  
    onMounted(() => {
        pageLoading.loading = true
        Promise.all([
            loadProvinceData(),loadMarketArea(),loadEnterpriseList(),
            loadAnchoringCenterList(),loadCementTypeAndPackageType(),loadAdministrativeAreaInfo(),
            loadDistrictData(),
            loadAnchoringCenterPriceInfo()
        ]).then(() => {
            // 销售区域
            return Promise.all([
                loadAllAreas(),loadAreaNearInfo(),
                loadAllMarketDepartmentAreaInfo(),loadMarketDepartmentNearInfo(),
                loadAllMarketCenterAreaInfo(),
                loadPriceSystemData()
            ])
        })
                .then(() => {
                    refreshColor()
                    refreshMarketDepartmentColor()
                    initMap()
                }).finally(() => {
            pageLoading.loading = false
        })
    })
    pageLoading.tip = '加载中'
  
  
    const simulateModalVisible = ref(false)
    const showSimulateModal = () => {
        simulateModalVisible.value = true
        anchoringCenterPriceInfo.value.forEach(item => {
            if(item.anchoringCenterId === simulateConfig.anchoringCenter) {
                simulateConfig.latestPrice = item.currentInPlacePrice
                simulateConfig.latestPriceDate = item.currentInPlacePriceDate
            }
        })
    }
    const simulateConfig = reactive({
        cementAndPackageType: 'P·O42.5水泥散装',
        anchoringCenter: undefined,
        latestPrice: 0,
        latestPriceDate: '2022-22-22',
        price: undefined
    })
    const handleSimulate = () => {
        // 开始模拟
        simulating.value = true
        priceSystemData.value = []
        loadPriceSystemData().then(() => {
            simulateModalVisible.value = false
        })
    }
    const handleCleanSimulate = () => {
        simulating.value = false
        priceSystemData.value = []
        loadPriceSystemData()
    }
    const anchoringCenterPriceInfo = ref([])
    const loadAnchoringCenterPriceInfo = () => {
        return post('/dynamic-price/api/v1/sand_map/anchoring_center_price/all', {
            cementTypeAndPackType: simulateConfig.cementAndPackageType
        }).then(resp => {
            anchoringCenterPriceInfo.value = (resp.data ?? [])
        })
    }
    const handleSimulateConfigAnchoringCenterChange = (e) => {
        simulateConfig.anchoringCenter = e.target.value
        // 刷新价格信息及时间信息
        anchoringCenterPriceInfo.value.forEach(item => {
            if(item.anchoringCenterId === simulateConfig.anchoringCenter) {
                simulateConfig.latestPrice = item.currentInPlacePrice
                simulateConfig.latestPriceDate = item.currentInPlacePriceDate
            }
        })
  
    }
  </script>
  <style lang="less" scoped>
    .page_root {
    width: 100%;
    height: 100%;
    overflow: auto;
    }
    .page_root :deep(.@{ant-prefix}-spin-nested-loading),
    .page_root :deep(.@{ant-prefix}-spin-container)
     {
        height: 100%;
    }
    .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper)
     {
        display: flex;
        flex-flow: column nowrap;
        justify-content: flex-start;
    }
    .page_root :deep(.@{ant-prefix}-table)
     {
      flex: auto;
      overflow: auto;
    }
    .table-moreBtn_down {
      overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: 100px;
    }
  
    .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
      background: #ebf1ff;
    }
  
    /*  表格树结构样式处理，展开按钮层级增加*/
    :deep(.@{ant-prefix}-table-row-expand-icon) {
      z-index: 1;
    }
    /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
    :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
      left: 15px !important;
      width: calc(100% - 15px);
    }
    :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
      left: 30px !important;
      width: calc(100% - 30px);
    }
    :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
      left: 45px !important;
      width: calc(100% - 45px);
    }
    :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
      left: 60px !important;
      width: calc(100% - 60px);
    }
  
    /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
    :deep(.@{ant-prefix}-transfer-list)
     {
        height: 100%;
        width: 50%;
    }
  
  
    .toolbar {
        height:64px;width:100%;
        padding: 0 24px;background:#FFF;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }
    .toolbar-left {
        display: flex;flex-direction: row;gap:16px;
    }
    .toolbar-right {
        display: flex;
        flex-direction: row;
        gap: 16px;
    }
    .view-switcher {
        width: 208px;height: 32px;
        background:#F5F5F5;border-right: 2px;padding: 4px;
        color:#595959;font-size:14px;text-align: center;
        display: flex;flex-direction: row;align-items: center;justify-content: center
    }
    .view-switcher-item {
        flex:1;
        cursor: pointer;
    }
    .view-switcher-item.active {
        background:#FFF;border-radius: 2px;  color: #d7000f;font-weight: 600;
    }
  
  
    .metric-box-wrapper {
        position: absolute;
        top: 84px;
        left: 24px;
        display: flex;
        flex-direction: row;
        gap: 8px;
    }
  
    .metric-box {
        background-image: linear-gradient(107deg, #FFFFFF 0%, #FFFFFF 23%, rgba(255,224,224,0.30) 100%);
        backdrop-filter: blur(6px);
        border: 2px solid #FFFFFF;
        box-shadow: 0 0 10px 0 rgba(127,66,66,0.09);
        border-radius: 8px;
        width: 236px;
        height: 72px;
        padding: 10px 24px;
  
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        .metric-item-box {
            display: flex;
            flex-direction: column;
            justify-content: center;
        }
        .metric-image {
            width: 52px;
            height: 42px;
            background-size:100% 100%;
        }
        .metric-image-1{
            background-image: url("");
        }
  
        .metric-image-2 {
            width: 47px;
            background-image: url("");
        }
  
        .metric-name {
            font-size: 14px;
            color: #262626;
            font-weight: 400;
        }
  
        .metric-value {
            font-size: 20px;
            color: #262626;
            letter-spacing: 0;
            font-weight: 600;
        }
  
        .metric-unit {
            font-size: 14px;
            color: #262626;
            letter-spacing: 0;
            font-weight: 400;
        }
  
        .metric-value-row {
            display: flex;
            flex-direction: row;
            align-items: baseline;
            gap: 4px;
        }
    }
    .legend-box {
        background:#FFF;min-width: 158px;border-radius: 2px;box-shadow: 0px 0px 4px 0px rgba(0,0,0,0.2);
        padding: 10px 13px;display: flex;flex-direction: column;gap: 12px;
        position: absolute;right:24px;bottom:24px;
    }
  </style>
  